﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using System.IO;

using MEFedMVVM.ViewModelLocator;
using Cinch;
using System.Configuration;
using System.Threading;

namespace Anata.Client
{

    /// <summary>
    /// Runtime implementation of the 
    /// Data service used by the <c>ImageLoaderViewModel</c> to obtain data
    /// </summary>
    [PartCreationPolicy(CreationPolicy.NonShared)]
    [ExportService(ServiceType.Runtime, typeof(IPromoProvider))]
    public class PromoProvider : IPromoProvider
    {
        #region Data
        private BackgroundTaskManager<int, List<Promo>> multiFetchBgWorker =
            new BackgroundTaskManager<int, List<Promo>>();
        private BackgroundTaskManager<int, Promo> singleFetchBgWorker =
            new BackgroundTaskManager<int, Promo>();
        private BackgroundTaskManager<Promo, Promo> singleUpdateBgWorker =
            new BackgroundTaskManager<Promo, Promo>();
        #endregion



        #region Public Methods/Properties

        public void LazyFetchPromos(int page, Action<List<Promo>> callback)
        {
            multiFetchBgWorker.TaskFunc = (argument) =>
                {
                    return FetchPromosInternal(argument);
                };

            multiFetchBgWorker.CompletionAction = (result) =>
                {
                    callback(result);
                };

            multiFetchBgWorker.WorkerArgument = page;
            multiFetchBgWorker.RunBackgroundTask();

        }

        public void LazyFetchPromo(int idPromo, Action<Promo> callback)
        {
            singleFetchBgWorker.TaskFunc = (argument) =>
            {
                return FetchPromoInternal(argument);
            };

            singleFetchBgWorker.CompletionAction = (result) =>
            {
                callback(result);
            };

            singleFetchBgWorker.WorkerArgument = idPromo;
            singleFetchBgWorker.RunBackgroundTask();

        }

        public void LazyUpdatePromo(Promo pPromo, Action<Promo> callback)
        {
            singleUpdateBgWorker.TaskFunc = (argument) =>
            {
                return UpdatePromoInternal(argument);
            };

            singleUpdateBgWorker.CompletionAction = (result) =>
            {
                callback(result);
            };

            singleUpdateBgWorker.WorkerArgument = pPromo;
            singleUpdateBgWorker.RunBackgroundTask();

        }
        /// <summary>
        /// To allow this class to be unit tested stand alone
        /// See CinchV1 articles about Unit Testing for this
        /// Or comments in Cinch BackgroundTaskManager<T> class
        /// </summary>
        public BackgroundTaskManager<int, List<Promo>> MultiFetchBgWorker
        {
            get { return multiFetchBgWorker; }
        }
        public BackgroundTaskManager<int, Promo> SingleFetchBgWorker
        {
            get { return singleFetchBgWorker; }
        }
        public BackgroundTaskManager<Promo, Promo> SingleUpdateBgWorker
        {
            get { return singleUpdateBgWorker; }
        }

        #endregion

        #region Private Methods
        private List<Promo> FetchPromosInternal(int page)
        {
            List<Promo> promos = new List<Promo>();
            //TODO: bener-bener konek ke database
            int pageSize = Int32.Parse(ConfigurationManager.AppSettings["LazyLoadPageSize"].ToString());
            using (AnataEntities context = new AnataEntities())
            {
                IQueryable<Promo> query =
                    from promo in context.Promo.Include("Layanan")
                    orderby promo.Nama
                    select promo;
                promos = query.Skip(page * pageSize).Take(pageSize).ToList();
            }
            return promos;
        }



        private Promo FetchPromoInternal(int idPromo)
        {
            Promo retval = new Promo();
            //AnataEntities context = new AnataEntities();
            //using (context)
            //{
            //    IQueryable<Promo> konsumenQuery =
            //        from konsumen in context.Promo
            //        orderby konsumen.Layanan.Nama
            //        where konsumen.IdPromo == idPromo
            //        select konsumen;
            //    retval = konsumenQuery.First();
            //}
            return retval;
        }



        private Promo UpdatePromoInternal(Promo pPromo)
        {
            //using (AnataEntities context = new AnataEntities())
            //{
            //    if (pPromo.IdPromo == 0)
            //    {
            //        context.AddToPromo(pPromo);
            //    }
            //    else
            //    {
            //        context.Attach(pPromo);
            //        // If the SalesOrderDetailID is not 0, then the item is not new
            //        // and needs to be updated. Because we already added the 
            //        // updated object to the context we need to apply the original values.
            //        // If we attached originalItem to the context 
            //        // we would need to apply the current values:
            //        // context.ApplyCurrentValues("SalesOrderDetails", updatedItem);
            //        // Applying current or original values, changes the state 
            //        // of the attached object to Modified.
            //        context.ObjectStateManager.ChangeObjectState(pPromo, System.Data.EntityState.Modified);
            //    }
            //    context.SaveChanges();
            //}
            return pPromo;
        }
        #endregion

    }
}
